<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>js 贪吃蛇</title>
    <style lang="css">
        * {
            margin: 0;
            padding: 0;
        }

        html,
        body {
            width: 100%;
            height: 100%;
        }

        body {
            position: relative;
        }

        #container {
            position: absolute;
            left: 0;
            top: 0;
            bottom: 0;
            right: 0;
            margin: auto;
            width: 800px;
            height: 600px;
            font-size: 0px;
            overflow: hidden;
        }

        span {
            display: inline-block;
            border: 1px solid #ccc;
            border-style: thin;
            border-collapse: collapse;
            box-sizing: border-box;
        }

        #container span.food {
            position: absolute;
            background-color: blue;
        }

        #container span.snake {
            position: absolute;
            background-color: red;
        }
    </style>
</head>

<body>
    <p>1、分析项目需求 使用键盘的方向键控制蛇的运动方向并吃到相应的食物。</p>
    <p>2、使用面向对象的思想分析贪吃蛇 面向对象的核心思想：把一个系统分解为若干个事务，每个事务就是一个类 分析贪吃蛇有哪些事务： 地图 食物 蛇</p>
    <p>3、确定项目的开发顺序 ① 地图 ② 食物 ③ 蛇</p>
    <p>4、定义地图类 在Javascript中，任何一个类都存在两部分：属性和方法 定义地图类： 属性： 宽度 ：800px 高度 ：400px 背景颜色：灰色 定位方式：absolute（绝对定位） 方法：show方法 用于显示地图.定义window.onload方法，实例化地图类</p>
    <p>5、定义食物类 食物类也有自己的属性和方法 属性： 宽度：20px 高度：20px 背景颜色：green 定位方式：absolute 横纵坐标：默认0和0 方法：show方法 用于随机显示食物.实例化食物类并显示在地图中.法：随机显示食物坐标
        横坐标：Math.floor(Math.random()*40) 纵坐标：Math.floor(Math.random()*20)</p>
    <p>6、定义蛇类 属性： 宽度：20 高度：20 定位方式：absolute 定义蛇节3节：使用数组保存蛇节，横坐标、纵坐标（横坐标连续，纵坐标相等），颜色 方法：show方法，用于显示蛇节信息. 实例化Snake类，显示蛇节信息</p>
    <p>7、让蛇运动起来,使用定时器让蛇运动起来</p>
    <p>8、定义setDirect方法，判断键盘键值并设置蛇的运动方向</p>
    <p>9、判断蛇是否吃到食物 如果蛇头坐标与食物坐标完全重合，代表吃到食物</p>

    <script type="text/javascript">
        (function (win) {
            var map,
                food,
                snake;
            var globalVar = {
                score: 0 // 得分
            }
            var blockages = {
                width: 50,
                height: 50,
                backgroundColor: 'blue',
                headBackgroundColor: 'red',
                color: '#ddd',
            }
            function Map() {
                this.id = 'container'
                this.width = 800
                this.height = 600
                this.row = 0
                this.rol = 0
                this.position = 'absolute'
                this.bgColor = ''
                this.dom = ''
                this.initFoodBody()
            }
            Map.prototype = {
                initFoodBody: function () {
                    var dom = document.createElement('div');
                    dom.id = this.id
                    dom.style.width = this.width + 'px'
                    dom.style.height = this.height + 'px'
                    dom.style.position = this.position
                    dom.style.backgroundColor = this.bgColor
                    document.body.appendChild(dom)
                    this.dom = dom
                },
                show: function () {

                    var containerDom = document.getElementById('container');
                    var newSpan = null;
                    var row = Math.floor(this.width / blockages.width)
                    var rol = Math.floor(this.height / blockages.height)
                    var num = row * rol;
                    this.row = row
                    this.rol = rol

                    for (var i = 0; i < num; i++) {
                        newSpan = document.createElement("span");
                        newSpan.className = "blockage blockage-" + i;
                        newSpan.style.width = blockages.width + "px";
                        newSpan.style.height = blockages.height + "px";
                        containerDom.appendChild(newSpan);
                    }
                }
            }
            function Food() {
                this.class = 'food'
                this.width = blockages.width
                this.height = blockages.height
                this.position = 'absolute'
                this.bgColor = 'green'
                this.x = 0
                this.y = 0
                this.dom = ''
                this.initFoodBody()
            }
            Food.prototype = {
                initFoodBody: function () {
                    var dom = document.createElement('span');
                    var randomPos = {}

                    dom.className = this.class
                    dom.style.width = this.width + 'px'
                    dom.style.height = this.height + 'px'
                    dom.style.position = this.position
                    dom.style.backgroundColor = this.bgColor

                    randomPos = this.randomPos()
                    dom.style.left = randomPos.x + 'px'
                    dom.style.top = randomPos.y + 'px'

                    this.x = randomPos.x / this.width
                    this.y = randomPos.y / this.height
                    this.dom = dom

                },
                show: function () {
                    document.getElementById('container').appendChild(this.dom)
                },
                randomPos: function () {
                    var containerDom = document.getElementById('container');
                    var containerDomBorderWidth = 2;

                    return {
                        x: Math.floor((containerDom.offsetWidth - containerDomBorderWidth) / this.width * Math.random()) * this.width,
                        y: Math.floor((containerDom.offsetHeight - containerDomBorderWidth) / this.height * Math.random()) * this.height,
                    }
                }
            }
            function Snake() {
                this.width = blockages.width
                this.height = blockages.height
                this.position = 'absolute'
                this.body = [
                    [4, 2, 'red'],
                    [3, 2, 'blue'],
                    [2, 2, 'blue'],
                    [1, 2, 'blue']
                ]
                this.speed = 400
                this.direct = 'right'
                this.initSnakeBody()
            }
            Snake.prototype = {
                move: function () {
                    var length = this.body.length

                    for (var i = length - 1; i > 0; i--) {
                        this.body[i][0] = this.body[i - 1][0]
                        this.body[i][1] = this.body[i - 1][1]
                    }
                    switch (this.direct) {
                        case 'right':
                            // this.body.forEach(function(item,index,arr){
                            //     arr[index][0] +=1
                            // })
                            this.body[0][0] += 1
                            break;
                        case 'left':
                            this.body[0][0] -= 1
                            break;
                        case 'up':
                            this.body[0][1] -= 1
                            break;
                        case 'down':
                            this.body[0][1] += 1
                            break;
                        default:
                            this.body[0][2] = 'blue'
                            break;
                    }
                    //如果超出边界，计算蛇头坐标
                    if (this.body[0][0] > map.row) {
                        this.body[0][0] = 0
                    }
                    if (this.body[0][0] < 0) {
                        this.body[0][0] = map.row
                    }
                    if (this.body[0][1] > map.rol) {
                        this.body[0][1] = 0
                    }
                    if (this.body[0][1] < 0) {
                        this.body[0][1] = map.rol
                    }
                    //1.如果吃到食物
                    if (this.isEatFood()) {
                        // 1.增加一节身体，即添加数组一项
                        globalVar.score += 1

                        this.body.push([food.x, food.y, 'blue'])
                        // 2.移除被吃掉食物
                        food = null;
                        var containerDom = document.getElementById('container');
                        containerDom.removeChild(document.querySelector('.food'));
                        // 2.创建新食物
                        food = new Food()
                        food.show()
                    }
                    this.show()
                },
                show: function () {
                    this.initSnakeBody()
                },
                setDirect: function (direct) {
                    this.direct = direct
                },
                isEatFood: function () {
                    if (this.body[0][0] == food.x && this.body[0][1] == food.y) {
                        return true
                    } else {
                        return false
                    }
                },
                initSnakeBody: function () {
                    var length = this.body.length
                    var containerDom = document.getElementById('container')

                    for (var i = length - 1; i >= 0; i--) {
                        var dom = document.querySelector('.blockage-' + i)
                        dom.style.position = this.position
                        dom.style.left = this.body[i][0] * this.width + 'px'
                        dom.style.top = this.body[i][1] * this.height + 'px'
                        dom.style.backgroundColor = this.body[i][2]
                    }
                }
            }
            win.onload = function () {
                // 1. 初始化地图
                map = new Map()
                map.show()
                // 2. 创建随机食物，并显示
                food = new Food()
                food.show()
                // 3. 创建蛇
                snake = new Snake()
                // 4. 让蛇动起来
                setInterval(function () {
                    snake.move()
                }, snake.speed);

                //4.控制蛇移动
                document.onkeyup = function (e) {
                    switch (e.keyCode) {
                        case 37:
                            snake.setDirect('left')
                            break;
                        case 38:
                            snake.setDirect('up')
                            break;
                        case 39:
                            snake.setDirect('right')
                            break;
                        case 40:
                            snake.setDirect('down')
                            break;
                    }
                }

            }
        })(window)
    </script>
</body>

</html>